package com.kestrel.space.user.filter;

import com.alibaba.fastjson.JSON;
import com.kestrel.space.user.model.User;
import com.kestrel.space.user.service.UserService;
import com.kestrel.space.common.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/**
 * @author GSZ
 * explain: token验证过滤器
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    private UserService userService;

    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse
            httpServletResponse, FilterChain filterChain) throws ServletException, IOException {

        // 从请求头中获取token
        String token = httpServletRequest.getHeader("token");

        // 如果token为空直接放行
        if (!StringUtils.hasText(token)) {
            filterChain.doFilter(httpServletRequest, httpServletResponse);
            // 后面也不必再执行
            return;
        }

        // 解析token
        Claims jwt;
        try {
            jwt = JwtUtil.parseJWT(token);
        } catch (Exception e) {
            // 如果解析失败 则token不合法
            e.printStackTrace();
            throw new RuntimeException("token不合法!");
        }

        // 从共享域中(session)中获取用户信息, 从解密出的用户id
        String jsonLoginUser = jwt.getSubject();

        // 反序列化json为对象
        User loginUser = JSON.parseObject(jsonLoginUser, User.class);

        // 判断是否存在数据
        if (Objects.isNull(loginUser)) throw new RuntimeException("用户未登陆");

        // 判断jwt数据正确性
        if (!checkUser(loginUser)) throw new RuntimeException("用户账号密码错误");

        // 封装对象信息
        UsernamePasswordAuthenticationToken authenticationToken = // todo 第三个参数是设置用户的权限信息
                new UsernamePasswordAuthenticationToken(loginUser, null, null);

        // 存储到security域中
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

        // 放行
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }

    protected boolean checkUser(User loginUser) {
        String passwordR = userService.getUser(loginUser.getId()).getPassword();
        return passwordR.equals(loginUser.getPassword());
    }
}
